import json
from datetime import datetime, time

from decimal import Decimal

from django import http
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator
from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.ausers.models import Address
from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from utils.response_code import RETCODE
import time




#个人订单展示
class OrderView(LoginRequiredMixin,View):
    def get(self,request,page_num):
        page_num = int(page_num)
        user = request.user
        orders = OrderInfo.objects.filter(user=user)

        for order in orders:
            details = []
            goods = order.skus.all()

            for good in goods:
                dict = {}
                dict['default_image_url'] = good.sku.default_image
                dict['name'] = good.sku.name
                dict['count'] = good.count
                dict['total_amount'] = good.count*good.price
                dict['price'] = good.price

                details.append(dict)
            order.details = details
        # 创建分页器
        paginator = Paginator(orders, 2)
        try:
            page_skus = paginator.page(page_num)
        except:
            # 如果page_num不正确，默认给用户404
            return http.HttpResponseNotFound('empty page')
        # 获取列表页总页数
        total_page = paginator.num_pages
        context = {'page':page_skus,
                   'total_page': total_page,
                   # 'total_page': total_page,
                   'page_num': int(page_num)
                   }
        return render(request,'user_center_order.html',context)

class OrderSettlementView(LoginRequiredMixin, View):
    """结算订单"""

    def get(self, request):
        """提供订单结算页面"""
        # 获取登录用户
        user = request.user

        # 1.查询地址
        try:
            addresses = Address.objects.filter(user=user, is_deleted=False)

        except:
            #  如果地址为空，渲染模板时会判断，并跳转到地址编辑页面
            addresses = None

        # 2.查询选中商品
        redis_client = get_redis_connection('carts')
        carts_data = redis_client.hgetall(user.id)
        # 转换格式
        carts_dict = {}
        for data in carts_data.items():
            sku_id = int(data[0].decode())
            sku_dict = json.loads(data[1].decode())
            if sku_dict['selected']:
                carts_dict[sku_id] = sku_dict

        # 3.计算金额 +邮费
        total_count = 0
        total_amount = Decimal(0.00)

        skus = SKU.objects.filter(id__in=carts_dict.keys())

        for sku in skus:
            sku.count = carts_dict[sku.id].get('count')
            sku.amount = sku.count * sku.price
            # 计算总数量和总金额
            total_count += sku.count
            total_amount += sku.count * sku.price

        # 运费
        freight = Decimal('10.00')

        # 4.构建前端显示的数据
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight,
            'default_address_id': user.default_address_id
        }
        return render(request, 'place_order.html', context)


class OrderCommitView(LoginRequiredMixin, View):
    def post(self, request):
        #   1. 接收解析解析参数 address_id payt_method
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        #   2. 校验 1.判空 2.地址是否有 3. pay-method是否
        if not all([address_id, pay_method]):
            return http.HttpResponseBadRequest('参数不齐!')
        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.HttpResponseBadRequest('收货地址不存在!')

        if int(pay_method) not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseBadRequest('支付方式不支持!')

        user = request.user
        # 3. 生成唯一 时间订单号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ("%09d" % user.id)

        from django.db import transaction
        with transaction.atomic():
            save_id = transaction.savepoint()

            try:
                # 4. 创建orderInfo这个数据 order,user,address,pay_method, freight: Deciaml(10.0)
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    pay_method=pay_method,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight=Decimal('10.0'),
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )

                #   5. 获取购物车redis数据 ; 商品必须选中状态
                redis_client = get_redis_connection('carts')
                client_data = redis_client.hgetall(user.id)
                carts_selected_dict = {}
                for data in client_data.items():
                    sku_id = int(data[0].decode())
                    sku_dict = json.loads(data[1].decode())
                    # 是否选中
                    if sku_dict['selected']:
                        carts_selected_dict[sku_id] = sku_dict

                # 6. 根据购物车 sku_ids 获取 skus商品 SKU
                sku_ids = carts_selected_dict.keys()
                # 使用查询集 querySet; 惰性执行, 缓存
                for sku_id in sku_ids:
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        # 获取老的库存和销量
                        origin_stock = sku.stock
                        origin_sales = sku.sales
                        #   7. 判断sku的库存量  购买的个数count > 库存量sku.stock: 购买失败
                        sku_count = carts_selected_dict[sku.id]['count']
                        if sku_count > sku.stock:
                            # 事务回滚
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})

                        # time.sleep(7)
                        # 8.sku 库存量减少, 销量增加
                        # sku.stock -= sku_count
                        # sku.sales += sku_count
                        # sku.save()

                        new_stock = origin_stock - sku_count
                        new_sales = origin_sales + sku_count

                        result = SKU.objects.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=new_sales)

                        # 如果库存足够的情况下 , 下单失败 ,应该是给多次机会 直到下单成功
                        if result == 0:
                            continue

                        #   9. spu 销量增加
                        sku.spu.sales += sku_count
                        sku.spu.save()

                        # 11. 订单商品表 创建 order,sku有关系属性
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            price=sku.price,
                            count=sku_count
                        )
                        # 10. 计算该sku的总价格, 总个数;
                        order.total_count += sku_count
                        order.total_amount += (sku_count * sku.price)

                        # 跳出死循环
                        break

                # 12. 累加运费, orderInfo.save()
                order.total_amount += order.freight
                order.save()

                # 事务提交
                transaction.savepoint_commit(save_id)
            except Exception as e:
                # 暴力回滚
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '订单失败!'})

        # 13. 清空选中购物车数据
        redis_client.hdel(user.id, *carts_selected_dict)

        # 14. 返回前端的响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})


class OrderSuccessView(LoginRequiredMixin, View):
    """提交订单成功"""

    def get(self, request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')

        context = {
            'order_id':order_id,
            'payment_amount':payment_amount,
            'pay_method':pay_method
        }
        return render(request, 'order_success.html', context)


class UncommentGoodsView(LoginRequiredMixin, View):
    """订单商品评价"""
    def get(self, request,pk):
        """
        提供订单商品评价界面
        :param request: 请求对象
        :return: 订单商品评价界面
        """

        goods=OrderGoods.objects.filter(order_id=pk,is_commented=False)
        # json_dict={}
        # ser=UncommentGoodsSerializers(goods,many=True)
        context = {
            'order_id': pk,
            'goods': goods
        }
        return render(request, 'goods_judge.html', context)


class CommentsView(LoginRequiredMixin, View):
    """订单商品评价"""
    def post(self, request):
        """
        从json中获取数据,序列化器验证数据,保存数据,返回响应
        :param request: 请求对象
        :return: json
        """
        json_dict = json.loads(request.body.decode())

        order_id = json_dict.get('order_id')
        sku_id = json_dict.get('sku_id')
        comment = json_dict.get('comment')
        score = json_dict.get('score')
        is_anonymous = json_dict.get('is_anonymous')

        ordergoods=OrderGoods.objects.get(order_id=order_id,sku_id=sku_id,is_commented=False)
        ordergoods.score=score
        ordergoods.comment = comment
        ordergoods.is_anonymous = is_anonymous
        ordergoods.is_commented = True
        ordergoods.save()

        orderinfo=ordergoods.order
        orderinfo.status = 5
        orderinfo.save()

        sku = ordergoods.sku
        sku.comments += 1
        sku.save()

        spu = sku.spu
        spu.comments += 1
        spu.save()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '评论成功', 'sku_id': sku_id})


class SKUSCommentsView(LoginRequiredMixin,View):
    """sku商品评价展示"""

    def get(self, request,pk):
        """
        获取sku商品id
        :param request: 请求对象
        :return: json
        """
        # is_commented = True
        ordergoods = OrderGoods.objects.filter(sku_id=pk)
        comments=[]
        for order in ordergoods:
            comment={}
            comment['comment']=order.comment
            comment['username']=order.order.user.username
            comment['score']=order.score
            if order.is_anonymous:
                comment['username']=comment['username'][0]+'***'+comment['username'][-1]
            comments.append(comment)

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '评论加载成功', 'comments': comments, 'sku_id': pk})